import { Constructor, ECSWorld } from "../ECSWorld";
import { ECSComponent } from "./ECSComponent";
import { ECSComponentSet } from "./ECSComponentSet";

const EMPTY: ECSComponent[] = [];

export class ECSComponentSetImpl implements ECSComponentSet {
    /**
     * 按照类型分组的所有组件
     */
    private components = new Map<string, ECSComponent[]>();

    constructor(readonly ecs: ECSWorld) {
        this.ecs = ecs;
    }

    size(): number {
        return this.components.size;
    }

    all<T extends ECSComponent>(constructor: Constructor<T>): T[] {
        const components = this.components.get(constructor.name);

        return components ? (components as T[]) : (EMPTY as T[]);
    }

    get<T extends ECSComponent>(constructor: Constructor<T>): T {
        const components = this.all<T>(constructor);
        if (components.length === 0) {
            throw new Error(
                `[ECS] not found component '${constructor.name}'`
            );
        }
        return components[0];
    }

    add(component: ECSComponent): void {
        const name = component.name;
        if (typeof name !== "string" || name.length === 0) {
            throw new Error(
                `[ECS] component '${component}' not set name by @ecsclass`
            );
        }

        let components = this.components.get(name);
        if (!components) {
            components = [];
            this.components.set(name, components);
        }
        components.push(component);
    }

    delete(component: ECSComponent): void {
        const components = this.components.get(component.name);
        if (components) {
            const i = components.indexOf(component);
            if (i >= 0) components.splice(i, 1);
        }
    }

}